using System;

using DirectShowLib;

namespace Engine.Media
{
    // Play State
    public enum PlayState
    {
        Stopped,
        Paused,
        Running,
        Init
    };

    // Super class Media
    public abstract class Media
    {
        // Default Attributes
        protected const int WMGraphNotify = 0x0400 + 13;
        protected const int VolumeFull = 0;
        protected const int VolumeSilence = -10000;

        protected IGraphBuilder graphBuilder = null;
        protected IMediaControl mediaControl = null;
        protected IMediaEventEx mediaEventEx = null;
        protected IMediaSeeking mediaSeeking = null;
        protected IMediaPosition mediaPosition = null;

        protected PlayState currentState = PlayState.Stopped;
        protected double currentPlaybackRate = 1.0;
        protected int currentVolume = 0;

        // Default Functions
        public void Play()
        {
            int hr = 0;

            // Reset status variables
            this.currentState = PlayState.Stopped;
            this.currentVolume = 0;

            // Run file
            hr = this.mediaControl.Run();
            DsError.ThrowExceptionForHR(hr);

            this.currentState = PlayState.Running;
        }

        public void Pause()
        {
            if (this.mediaControl == null)
                return;

            // Toggle play / pause behavior
            if ((this.currentState == PlayState.Paused) || (this.currentState == PlayState.Stopped))
            {
                if (this.mediaControl.Run() >= 0)
                    this.currentState = PlayState.Running;
            }
            else
            {
                if (this.mediaControl.Pause() >= 0)
                    this.currentState = PlayState.Paused;
            }
        }

        public void Stop()
        {
            if ((this.mediaControl == null) || (this.mediaSeeking == null))
                return;

            int hr = 0;
            DsLong pos = new DsLong(0);

            // Stop and reset postion to beginning
            if ((this.currentState == PlayState.Paused) || (this.currentState == PlayState.Running))
            {
                hr = this.mediaControl.Stop();
                this.currentState = PlayState.Stopped;

                // Seek to the beginning
                hr = this.mediaSeeking.SetPositions(pos, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);

                // Display the first frame to indicate the reset condition
                hr = this.mediaControl.Pause();
            }
        }

        // Accessors
        public IMediaPosition Position
        {
            get { return mediaPosition; }
        }

        public PlayState State
        {
            get { return currentState; }
            set { currentState = value; }
        }

        public double PlaybackRate
        {
            get { return currentPlaybackRate; }
            set { currentPlaybackRate = value; }
        }

        public int Volume
        {
            get { return currentVolume; }
            set { currentVolume = value; }
        }
    }
}
